ZxtCalendarImagePath = zxt.cfg.IMAGES_PATH;

/**
 * <p>
 * 日历类
 * </p>
 * 
 * @class 日历类
 */
zxt.ui.Calendar = function() {
	zxt.ui.Widget.call(this);

	this.weekDayName = new Array("日", "一", "二", "三", "四", "五", "六");
	this.monthName1 = new Array("1", "2", "3", "4", "5", "6", "7", "8", "9",
			"10", "11", "12");
	this.monthName2 = new Array("JAN", "FEB", "MAR", "APR", "MAY", "JUN",
			"JUL", "AUG", "SEP", "OCT", "NOV", "DEC");
	this._target = null;
	this.locElement = null;
	this.format = "yyyy-mm-dd";

	this._selectYear = null;
	this._selectMonth = null;
	this._selectDay = null;
	this._selectYearStart = 2007;
	this._selectYearRange = 3;

	this._jCalendarDIV = null;
	this._jYearSelectDIV = null;
	this._jMonthSelectDIV = null;
	this._jqHeaderTable = null;
	this._jqSpanYear = null;
	this._jqSpanMonth = null;
	this._jqContentTable = null;
};

//直接继承Widget类
zxt.defineClazz(zxt.ui.Calendar, zxt.ui.Widget);

/**
 * <p>
 * 返回周信息
 * </p>
 * 
 * @function
 * @param {Date} n 日期对象
 * @returns {number} "week"
 */
zxt.ui.Calendar.prototype.getWeekNbr = function(n) {
	year = n.getFullYear();
	month = n.getMonth() + 1;
	day = n.getDate() + 1;
	a = Math.floor((14 - month) / 12);
	y = year + 4800 - a;
	m = month + 12 * a - 3;
	b = Math.floor(y / 4) - Math.floor(y / 100) + Math.floor(y / 400);
	J = day + Math.floor((153 * m + 2) / 5) + 365 * y + b - 32045;
	d4 = (((J + 31741 - (J % 7)) % 146097) % 36524) % 1461;
	L = Math.floor(d4 / 1460);
	d1 = ((d4 - L) % 365) + L;
	week = Math.floor(d1 / 7) + 1;
	return week;
};

/**
 * <p>
 * 返回一个年月的日期
 * </p>
 * 
 * @function
 * @param {string} year 年份
 * @param {string} month 月份
 * @returns {Array}  日期数组
 */
zxt.ui.Calendar.prototype.getNumberDaysInMonth = function(year, month) {
	var aNumDays = Array(31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
	var endDate;
	if (month == 1) {
		endDate = new Date(year, month + 1, 1);
		endDate = new Date(endDate - (24 * 60 * 60 * 1000));
		return endDate.getDate();
	} else {
		return aNumDays[month];
	}
};

/**
 * <p>
 * 返回一个格式化的日期
 * </p>
 * 
 * @function
 * @param {string} y 年份
 * @param {string} m 月份
 * @param {string} d 日期
 * @returns {string}  格式化后的日期
 */
zxt.ui.Calendar.prototype._constructDate = function(d, m, y) {
	var sTmp = this.format;
	sTmp = sTmp.replace("dd", "<e>");
	sTmp = sTmp.replace("d", "<d>");
	var pad_d = (d < 10) ? '0' + d : d;
	sTmp = sTmp.replace("<e>", pad_d);
	sTmp = sTmp.replace("<d>", d);
	sTmp = sTmp.replace("mmmm", "<p>");
	sTmp = sTmp.replace("mmm", "<o>");
	sTmp = sTmp.replace("mm", "<n>");
	sTmp = sTmp.replace("m", "<m>");
	sTmp = sTmp.replace("<m>", m);
	var pad_m = (m < 10) ? '0' + m : m;
	sTmp = sTmp.replace("<n>", pad_m);
	sTmp = sTmp.replace("<o>", this.monthName1[m - 1]);
	sTmp = sTmp.replace("<p>", this.monthName2[m - 1]);
	sTmp = sTmp.replace("yyyy", y);
	var _y = y % 100;
	var pad_y = (_y < 10) ? '0' + _y : _y;
	return sTmp.replace("yy", pad_y);
};

/**
 * <p>
 * 根据日期字符串设置日历的日期。如果没有传参数，则设置为当前日期
 * </p>
 * 
 * @function
 * @param {string} dstr 日期字符串
 */
zxt.ui.Calendar.prototype._parseDate = function(dstr) {

	if (dstr == undefined) {
		var nDate = new Date();
		this._selectYear = nDate.getFullYear();
		this._selectMonth = nDate.getMonth();
		this._selectDay = nDate.getDate();
	}

	//TODO：格式字符串分解有问题
	var ftChar = " ";
	var dateFormat = this.format;
	var aFormat = dateFormat.split(ftChar);
	if (aFormat.length < 3) {
		ftChar = "/";
		aFormat = dateFormat.split(ftChar);
		if (aFormat.length < 3) {
			ftChar = ".";
			aFormat = dateFormat.split(ftChar);
			if (aFormat.length < 3) {
				ftChar = "-";
				aFormat = dateFormat.split(ftChar);
				if (aFormat.length < 3) {
					ftChar = "";
				}
			}
		}
	}

	var tokensChanged = 0;
	var aData = dstr.split(ftChar);

	for (i = 0; i < 3; i++) {
		if ((aFormat[i] == "d") || (aFormat[i] == "dd")) {
			this._selectDay = parseInt(aData[i], 10);
			tokensChanged++;
		} else if ((aFormat[i] == "m") || (aFormat[i] == "mm")) {
			this._selectMonth = parseInt(aData[i], 10);
			tokensChanged++;
		} else if (aFormat[i] == "yyyy") {
			this._selectYear = parseInt(aData[i], 10);
			tokensChanged++;
		} else if (aFormat[i] == "mmm") {
			for (j = 0; j < 12; j++) {
				if (aData[i] == mtName[j]) {
					this._selectMonth = j + 1;
					tokensChanged++;
				}
			}
		} else if (aFormat[i] == "mmmm") {
			for (j = 0; j < 12; j++) {
				if (aData[i] == mtName2[j]) {
					this._selectMonth = j + 1;
					tokensChanged++;
				}
			}
		}
	}

	if ((tokensChanged != 3) || isNaN(this._selectDay)
			|| isNaN(this._selectMonth) || isNaN(this._selectYear)) {
		this._selectYear = null;
		this._selectMonth = null;
		this._selectDay = null;
		if (dstr.length == 8) {
			var valuestr = dstr;
			var nanflage = false;
			for ( var i = 0; i < valuestr.length; i++) {
				if (valuestr.charAt(i) < '0' || valuestr.charAt(i) > '9')
					nanflage = true;
			}
			aData = [ dstr.substring(0, 4), dstr.substring(4, 6),
					dstr.substring(6, 8) ];

			this._selectDay = parseInt(aData[2], 10);
			this._selectMonth = parseInt(aData[1], 10);
			this._selectYear = parseInt(aData[0], 10);

			if (this._selectMonth > 12 || nanflage) {
				this._selectYear = null;
				this._selectMonth = null;
				this._selectDay = null;
			}
		}
	}
};


/**
 * <p>
 * 设置日历控件的目标Datebox控件
 * 不传参的话返回目标Datebox控件
 * </p>
 * 
 * @function
 * @param {zx.ui.Datebox} v 日期控件
 * @return {zx.ui.Datebox} 日期控件
 */
zxt.ui.Calendar.prototype.target = function(v) {
	if (v == undefined) {
		return this._target;
	}
	this._target = v;
	var dv = v.val();
	if (dv == undefined) {
		dv = "";
	}
	this._parseDate(dv);
};

/**
 * <p>
 * 设置日历控件的月份
 * </p>
 * 
 * @function
 * @param {string} month 月份数
 */
zxt.ui.Calendar.prototype._selMonth = function(month) {
	this._selectMonth = month;
	this._showMonth(false);
	this.render();
};

/**
 * <p>
 * 设置日历控件的年份
 * </p>
 * 
 * @function
 * @param {string} year 年份数
 */
zxt.ui.Calendar.prototype._selYear = function(year) {
	this._selectYear = this._selectYearStart + year;
	this._showYear(false);
	this.render();
};

/**
 * <p>
 * 增减年份 单位1年 同时更改年份选择下拉列表的值
 * </p>
 * 
 * @function
 * @param {boolean} dir true时表示年份增加 false时表示年份减少
 */
zxt.ui.Calendar.prototype._moveYear = function(dir) {
	dir ? this._selectYearStart++ : this._selectYearStart--;
	for (i = 0 - this._selectYearRange; i <= this._selectYearRange; i++) {
		var year = this._selectYearStart + i;
		$("td", this._jYearSelectDIV).eq(i + this._selectYearRange + 1).html(
				year);
	}
};

/**
 * <p>
 * 增减月份 单位1月 同时更改月份选择下拉列表的值
 * </p>
 * 
 * @function
 * @param {boolean} dir true时表示月份增加 false时表示月份减少
 */
zxt.ui.Calendar.prototype._moveMonth = function(dir) {
	dir ? this._selectMonth++ : this._selectMonth--;
	if (this._selectMonth <= 0) {
		this._selectMonth = 12;
		this._selectYear--;
	} else if (this._selectMonth > 12) {
		this._selectMonth = 1;
		this._selectYear++;
	}
	this.render();
};

/**
 * <p>
 * 显示或隐藏年份的下拉列表
 * </p>
 * 
 * @function
 * @param {boolean} b true时表示显示 false时表示隐藏
 */
zxt.ui.Calendar.prototype._showYear = function(b) {
	this._jYearSelectDIV.css("z-index", b ? "999" : "997");
	this._jYearSelectDIV.css("display", b ? "block" : "none");
};

/**
 * <p>
 * 显示或隐藏月份的下拉列表
 * </p>
 * 
 * @function
 * @param {boolean} b true时表示显示 false时表示隐藏
 */
zxt.ui.Calendar.prototype._showMonth = function(b) {
	this._jMonthSelectDIV.css("z-index", b ? "999" : "997");
	this._jMonthSelectDIV.css("display", b ? "block" : "none");
};

/**
 * <p>
 * 单击年份事件
 * </p>
 * 
 * @function
 */
zxt.ui.Calendar.prototype.yearSpanClicked = function() {
	this._showYear(true);
	zxt.util.dom.postionWithRel(this._jYearSelectDIV.get(0), this._jqSpanYear
			.get(0), false, this._border, this._padding, this._shaddow);
};

/**
 * <p>
 * 单击月份事件
 * </p>
 * 
 * @function
 */
zxt.ui.Calendar.prototype.monthSpanClicked = function() {
	this._showMonth(true);
	zxt.util.dom.postionWithRel(this._jMonthSelectDIV.get(0), this._jqSpanMonth
			.get(0), false);
};

/**
 * <p>
 * 单击日历上的日期事件
 * </p>
 * 
 * @function
 */
zxt.ui.Calendar.prototype.dateClicked = function(d) {
	if (this.target() != null) {
		var d = this._constructDate(d, this._selectMonth, this._selectYear);
		this.target().renderValue(d);
	}
	;
	this.show(false);
};

/**
 * <p>
 * 单击日历上的清除事件
 * </p>
 * 
 * @function
 */
zxt.ui.Calendar.prototype.clearClicked = function() {
	if (this.target() != null) {
		this.target().renderValue("");
	}
	this.show(false);
};

/**
 * <p>
 * 单击日历上的关闭按钮事件
 * </p>
 * 
 * @function
 */
zxt.ui.Calendar.prototype.closeClicked = function() {
	this.show(false);
};

/**
 * <p>
 * 显示日历方法
 * 渲染出日历节点
 * </p>
 * @function
 * @param {boolean} b 日历控件是否展示
 */
zxt.ui.Calendar.prototype.show = function(b) {
	this.render();
	this._jCalendarDIV.css("display", b ? "block" : "none");
	var d =$(window).width()-$(this.locElement).offset().left;
	if(d<200){
		this._jCalendarDIV.css("margin-left","-200px");
	}else{
		this._jCalendarDIV.css("margin-left","0px");
	}
	zxt.util.dom.postionWithRel(this._jCalendarDIV.get(0), this.locElement,
			false);
};

/**
 * <p>
 * 渲染日历控件节点方法
 * </p>
 * @function
 * @return {DOM} 渲染好的DOM节点
 */
zxt.ui.Calendar.prototype.renderSelf = function() {
	var h = this;
	if (this._selectYear == null || this._selectMonth == null
			|| this._selectDay == null) {
		var today = new Date();
		this._selectYear = today.getFullYear();
		this._selectMonth = today.getMonth() + 1;
		this._selectDay = today.getDate();
	}

	if (this._jCalendarDIV == null) {
		this._jCalendarDIV = $("<div nowrap style='z-index:+998;position:absolute;display:none;width:220'/>");

		var jqNavTr = $("<tr bgcolor='#A3B9C5' height='25'>").append(
				$("<td>").append(this._renderHeader()));
		var jqTr = $("<tr>").append(
				$("<td style='padding:1px' bgcolor=#ffffff>").append(
						this._renderContent()));
		var jqToTr = $("<tr bgcolor=#A3B9C5>").append(
				$("<td align=center>").append(this._renderTail()));
		var jqTbody = $("<tbody>").append(jqNavTr).append(jqTr).append(jqToTr);

		var jqContentTable = $(
				"<table width=180 cellspacing=0 cellpadding=0 style='font-family:arial;font-size:10pt;border-width:1;border-style:solid;border-color:#a0a0a0;font-family:arial; font-size:11pt}' bgcolor='#ffffff'>")
				.append(jqTbody);
		var jqIframe = $("<iframe src='javascript:false' style='position:absolute;display:inherit;top:0px;left:0px;width:100%;height:100%;z-index:-1;filter=\"progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)\";'></iframe>");

		this._jCalendarDIV.append(jqContentTable).append(jqIframe);

		var selectionDiv = "<div style='z-index:+997;position:absolute;display:none;width:60'></div>";
		var selectionTb = "<table style='font-family:arial; font-size:9pt; border-width:1; border-style:solid; border-color:#a0a0a0;background-color:#A3B9C5;border-top:1px solid #999999;border-left:1px solid #999999;border-right:1px solid #999999;padding-left:1px;padding-right:1px;' cellspacing=0/>";
		var selTd = "<td align='center' onmouseover='this.style.backgroundColor=\"#d2eaf6\"' onmouseout='this.style.backgroundColor=\"\"' style='cursor:pointer;background-color:#A3B9C5;border-top:1px solid #999999;border-left:1px solid #999999;border-right:1px solid #999999;padding-left:1px;padding-right:1px;'/>";

		/* create year selection DIV */
		var jqYearSelectTable = $(selectionTb).attr("width", "44");
		jqYearSelectTable.mouseover(function() {
			clearTimeout(this.timeoutID2);
		});
		jqYearSelectTable.mouseout(function() {
			clearTimeout(this.timeoutID2);
			this.timeoutID2 = setTimeout(function() {
				h._showYear(false)
			}, 100);
		});

		var jqTd = $("<td align='center' style='cursor:pointer'>-</td>");
		jqTd.mouseover(function() {
			this.style.backgroundColor = "#d2eaf6";
		});
		jqTd.mouseout(function() {
			this.style.backgroundColor = "";
		});
		jqTd.mousedown(function() {
			this._incYearInterval = setInterval(function() {
				h._moveYear(false);
			}, 30);
		});
		jqTd.mouseup(function() {
			clearInterval(this._incYearInterval);
		});
		var jqYearTbody = $("<tbody>").append($("<tr>").append(jqTd));

		for (i = 0 - this._selectYearRange; i <= this._selectYearRange; i++) {
			var year = this._selectYearStart + i;
			var jqYearTd = $(selTd).html("&nbsp;" + year + "&nbsp;");
			jqYearTd.get(0).offsetYear = i;
			jqYearTd.click(function() {
				h._selYear(this.offsetYear);
			});
			jqYearTbody.append($("<tr>").append(jqYearTd));
		}
		;

		jqTd = $("<td align='center' style='cursor:pointer'>+</td>");
		jqTd.mouseover(function() {
			this.style.backgroundColor = "#d2eaf6";
		});
		jqTd.mouseout(function() {
			this.style.backgroundColor = "";
		});
		jqTd.mousedown(function() {
			this._incYearInterval = setInterval(function() {
				h._moveYear(true);
			}, 30);
		});
		jqTd.mouseup(function() {
			clearInterval(this._incYearInterval);
		});
		jqYearTbody.append($("<tr>").append(jqTd));

		jqYearSelectTable.append(jqYearTbody);
		this._jYearSelectDIV = $(selectionDiv).append(jqYearSelectTable);
		document.body.appendChild(this._jYearSelectDIV.get(0));

		/* create month selection DIV */
		var jqMonthSelectTable = $(selectionTb);
		jqMonthSelectTable.attr("width", "30");
		jqMonthSelectTable.mousemove(function() {
			clearTimeout(this.timeoutID);
		});
		jqMonthSelectTable.mouseout(function(e) {
			clearTimeout(this.timeoutID);
			this.timeoutID = setTimeout(function() {
				h._showMonth(false)
			}, 100);
		});

		var jqMonthTbody = $("<tbody>");
		for (i = 0; i < 12; i++) {
			var month = i + 1;
			var jqMonthTd = $(selTd).html("&nbsp;" + month + "&nbsp;");
			;
			jqMonthTd.get(0).month = month;
			jqMonthTd.click(function() {
				h._selMonth(this.month);
			});
			jqMonthTbody.append($("<tr>").append(jqMonthTd));
		}
		;

		jqMonthSelectTable.append(jqMonthTbody);
		this._jMonthSelectDIV = $(selectionDiv).append(jqMonthSelectTable);
		document.body.appendChild(this._jMonthSelectDIV.get(0));

	} else {
		this._renderHeader();
		this._renderContent();
		this._renderTail();
	}
	;
	return this._jCalendarDIV.get(0);
};

/**
 * <p>
 * 渲染日历控件标题节点方法
 * </p>
 * @function
 * @return {DOM} 渲染好的DOM节点
 */
zxt.ui.Calendar.prototype._renderHeader = function() {
	var h = this;
	if (this._jqHeaderTable == null) {
		this._jqHeaderTable = $("<table width='100%' cellspacing=0 cellpadding=0>");
	}
	this._jqHeaderTable.empty();

	var jqTr = $("<tr>");
	var jqTd = $("<td style='padding:1px;font-family:arial; font-size:11pt;'>");

	var spanLR = "<span style='cursor:pointer;background-color:#A3B9C5;font-size:10px;text-align: center;' >&nbsp<IMG SRC='"
			+ ZxtCalendarImagePath;
	var jqSpanLeft = $(spanLR + "/efcalendar_left1.gif'>&nbsp</span>").click(
			function() {
				h._moveMonth(false);
			});
	var jqSpanRight = $(spanLR + "/efcalendar_right1.gif'>&nbsp</span>").click(
			function() {
				h._moveMonth(true);
			});

	var spanHTML = "<span style='cursor:pointer;font-size:11px;text-align: center;border-bottom:1px solid #e4db83;border-right:1px solid #e4db83;border-left:1px solid #ffffff;border-top:1px solid #ffffff;border-color:#8bc2df;' onmouseover='this.style.borderColor=\"#d2eaf6\";' onmouseout='this.style.borderColor=\"#8bc2df\";'></span>";
	var jqSpanYear = $(spanHTML).click(function() {
		h.yearSpanClicked();
	});
	var jqSpanMonth = $(spanHTML).click(function() {
		h.monthSpanClicked();
	});

	var spanYMPart0 = "&nbsp;<span style='font-size:11px;font-weight:Bold;color:#505050;text-align:center;'>";
	var spanYMPart1 = "</span>&nbsp;<span align='center' style='cursor:pointer;background-color:#A3B9C5;font-size:10px;text-align: center;'> <IMG  SRC='"
			+ ZxtCalendarImagePath + "/efcalendar_drop1.gif' >&nbsp</span>";
	jqSpanYear.html(spanYMPart0 + this._selectYear + spanYMPart1);
	jqSpanMonth.html(spanYMPart0 + this._selectMonth + spanYMPart1);

	var yearMonth = "<span style='font-size:11px;font-weight:Bold;color:#505050;text-align:center;'></span>";
	var jqYear = $(yearMonth).html("年");
	var jqMonth = $(yearMonth).html("月");

	this._jNavDIV = $("<span/>").append(jqSpanLeft).append(jqSpanRight).append(
			jqSpanYear).append(jqYear).append(jqSpanMonth).append(jqMonth);
	jqTr.append(jqTd.append(this._jNavDIV));

	var jqTd2 = $("<td align=right >");
	var jqClose = $("<a href='#'><IMG SRC='"
			+ ZxtCalendarImagePath
			+ "/efcalendar_icon.gif' WIDTH='15' HEIGHT='13' BORDER='0' ALT='close'></a>");
	jqClose.click(function() {
		h.closeClicked();
	});
	jqTd2.append(jqClose);

	jqTr.append(jqTd2);
	var jqTbody = $("<tbody>").append(jqTr);
	this._jqHeaderTable.append(jqTbody);

	this._jqSpanYear = jqSpanYear;
	this._jqSpanMonth = jqSpanMonth;
	return this._jqHeaderTable.get(0);
};

/**
 * <p>
 * 渲染日历控件内容节点方法
 * </p>
 * @function
 * @return {DOM} 渲染好的DOM节点
 */
zxt.ui.Calendar.prototype._renderContent = function() {
	var _y = this._selectYear;
	var _m = this._selectMonth - 1;
	var h = this;
	var numDaysInMonth = this.getNumberDaysInMonth(_y, _m);

	if (this._jqContentTable == null) {
		this._jqContentTable = $("<table cellpadding=1 cellspacing=0>");
	}
	this._jqContentTable.empty();
	var jqTbody = $("<tbody>");
	this._jqContentTable.append(jqTbody);

	var headHtml = "<tr bgcolor='#f7f8fd'><td width=15><b>周</b></td><td width=1 rowspan=7 bgcolor='#d0d0d0' style='padding:0px'><img src='"
			+ ZxtCalendarImagePath + "/efcalendar_divider.gif' width=1></td>";
	for (i = 0; i < 7; i++) {
		headHtml += "<td width='15' align='right'><b>&nbsp;&nbsp;"
				+ this.weekDayName[i] + "</b></td>";
	}
	headHtml += "</tr>";
	var jqTr = $(headHtml);
	jqTbody.append(jqTr);

	var _s = new Date(_y, _m, 1);
	var nIndex = 1 - _s.getDay();
	do {
		var jqWeekTr = $("<tr/>");
		var firstDay = nIndex < 1 ? 1 : nIndex;
		var jqTd = $("<td align=right>"
				+ this.getWeekNbr(new Date(_y, _m, firstDay)) + "</td>");
		jqWeekTr.append(jqTd);

		for ( var wi = 0; wi < 7; wi++) {
			jqTd = $("<td align=right></td>");
			if (nIndex > 0 && nIndex <= numDaysInMonth) {
				var jqDate = $("<a href='#' style='text-decoration:none;color:black;font-size:11px;' onmousemove='this.style.backgroundColor=\"#d2eaf6\"' onmouseout='this.style.backgroundColor=\"#ffffff\"'>&nbsp;"
						+ nIndex + "&nbsp;</a>");
				jqDate.get(0).dayIdx = nIndex;
				jqDate.click(function() {
					h.dateClicked(this.dayIdx);
				});
				jqTd.append(jqDate);
			} else {
				jqTd.html('&nbsp;');
			}
			;
			jqWeekTr.append(jqTd);
			nIndex++;
		}
		;
		jqTbody.append(jqWeekTr);
	} while (nIndex <= numDaysInMonth);
	return this._jqContentTable.get(0);
};

/**
 * <p>
 * 渲染日历控件底部按钮节点方法
 * </p>
 * @function
 * @return {DOM} 渲染好的DOM节点
 */
zxt.ui.Calendar.prototype._renderTail = function() {
	var today = new Date();
	var toStr = this._constructDate(today.getDate(), today.getMonth() + 1,
			today.getFullYear());
	var h = this;
	if (this._jqTail == null) {
		this._jqTail = $("<span>");
	}
	;

	this._jqTail.empty();
	var c = $("<a href='#'>[清空]</a>").click(function() {
		h.clearClicked()
	});
	var t = $("<span>&nbsp;今天是 </span>");
	var s = $("<a href='#'>" + toStr + "</a>");
	if (this._target != null) {
		s.click(function() {
			h.target().renderValue($(this).html());
			h.closeClicked();
		});
	}
	;

	this._jqTail.append(c).append(t).append(s);
	return this._jqTail.get(0);
};

zxt.ui.Calendar._instance = null;

/**
 * <p>
 * 展示日历控件方法
 * </p>
 * @function
 * @param {DOM} showEl 弹框展示位置的DOM节点
 * @param {ZXTUI} targetEl 日历框的值输出输入目标控件
 * @param {string} format 日历控件输出的日期格式
 * @param {boolean} rightPosition 是否弹出在右侧
 * EXP： zxt.ui.Calendar.show(this._jqImageDom, this._textbox, this.$Format, true);
 */
zxt.ui.Calendar.show = function(showEl, targetEl, format, rightPosition) {
	if (zxt.ui.Calendar._instance == null) {
		zxt.ui.Calendar._instance = new zxt.ui.Calendar();
		document.body.appendChild(zxt.ui.Calendar._instance.render());
	}
	zxt.ui.Calendar._instance.format = format;
	zxt.ui.Calendar._instance.target(targetEl);
	zxt.ui.Calendar._instance.locElement = showEl;
	zxt.ui.Calendar._instance.show(true);
};


/**
 * <p>
 * 日期控件类
 * 默认的日期格式为 "yyyy-mm-dd"
 * </p>
 * @class 日期控件类
 * @param {string} tip 日期控件显示的提示内容
 * @param {boolean} required 是否为必填内容
 */
zxt.ui.Datebox = function(tip, required) {
	zxt.ui.Composite.call(this);
	zxt.ui.Interactor.call(this);

	this.$Format = "yyyy-mm-dd";
	this.$Hide = "";

	this._tip = tip;
	this._img = null;
	this._required = (required == true || required == "true");

	this._skeleton = null;
	this._inner = null;
	this._$holderPanel = null;
	this._$holderPanelDom = null;

	this._textbox = new zxt.ui.Textbox(required, tip);//日期控件输入框
	this.addChild(this._textbox);

	var _instance = this;
	
	//重载输入框的校验方法
	this._textbox.validate = function(value) {
		return _instance.validate(_instance, value);
	};
	
	this._textbox.validateStatus = function(v, type, param, info) {
		var parent = this.getParent();
		if (zxt.util.isValue(parent)) {
			return parent.validateStatus(v, type, param, info);
		}
	};
	
	this._jqImage = null;//日期控件的图片
};

/**
 * <p>
 * 根据传入的DOM元素, 解析传入的相关属性, 创建相应的区域
 * </p>
 * @function
 * @static
 * @param {DOM} elem 传入的DOM元素
 * @return {zxt.ui.Datebox} 创建的日期控件对象
 */
zxt.ui.Datebox.parse = function(elem) {
	var j = $(elem);
	var _tip = j.attr("zxt.tip");
	var _val = j.attr("zxt.value");
	var _format = j.attr("zxt.format");
	var _required = j.attr("zxt.required");
	var _formatType = j.attr("zxt.formatType");

	var tip = _tip || _format.toUpperCase();

	var _instance = new zxt.ui.Datebox(tip, _required);
	if (zxt.util.isValue(_format)) {
		_instance.format(_format);
	}
	;

	var _hide = j.attr("zxt.hide") || "";
	_instance.$Hide = _hide;

	_instance.setValue(_val);

	_instance._textbox.formatType(_formatType);

	return _instance;
};

zxt.defineClazz(zxt.ui.Datebox, zxt.ui.Interactor, zxt.ui.Composite);

/**
 * <p>
 * 返回控件类型
 * </p>
 * 
 * @function
 * @return {string} “zxt.ui.Datebox"
 */
zxt.ui.Datebox.prototype.getType = function() {
	return "zxt.ui.Datebox";
};

/**
 * <p>
 * 设置日期显示格式
 * </p>
 * 
 * @function
 * @param {string} v 日期格式
 * @return {string}  如果不传参 返回日期格式
 */
zxt.ui.Datebox.prototype.format = function(v) {
	if (v === undefined) {
		return this.$Format;
	}
	this.$Format = v;
};

/**
 * <p>
 * 检查是不是设置了格式化
 * </p>
 * 
 * @function
 * @param {boolean} v 是不是设置了格式化
 * @return {boolean}  如果不传参 返回是不是设置了格式化
 */
zxt.ui.Datebox.prototype.image = function(v) {
	if (v !== undefined) {
		this._img = v;
		return;
	}
	if (zxt.util.isValue(this._img)) {
		return this._img;
	}
	if (zxt.util.isValue(this.$Format)) {
		if ((zxt.util.stringContains(this.$Format, "y") || zxt.util
				.stringContains(this.$Format, "Y"))
				&& (zxt.util.stringContains(this.$Format, "m") || zxt.util
						.stringContains(this.$Format, "M"))
				&& (zxt.util.stringContains(this.$Format, "d") || zxt.util
						.stringContains(this.$Format, "D"))) {
			return true;
		}
	}
	return false;
};

/**
 * <p>
 * 日期控件校验方法
 * </p>
 * 
 * @function
 * @param {zxt.ui.Datebox} instance 日期控件对象
 * @param {string} value 日期控件值
 * @return {string[]}  校验结果
 */
zxt.ui.Datebox.prototype.validate = function(instance, value) {
	if (!zxt.util.isAvailable(value)) {
		if (this._required) {
			this.validateStatus(false, zxt.core.ValidatorType.REQUIRED);
			return [ "不能为空" ];
		} else {
			this.validateStatus(true);
			return [];
		}
	}
	if (!instance._validate(value)) {
		this.validateStatus(false, "格式不正确 " + this.format());
		return [ "格式不正确 " + this.format() ];
	} else {
		this.validateStatus(true);
		return [];
	}
	return [];
};

/**
 * <p>
 * 配置控件
 * </p>
 * 
 * @function
 * @param {Object} conf 配置对象
 */
zxt.ui.Datebox.prototype.conf = function(conf) {
	this.config(conf);
};

/**
 * <p>
 * 配置控件
 * </p>
 * 
 * @function
 * @param {Object} conf 配置对象
 */
zxt.ui.Datebox.prototype.config = function(conf) {
	this._config(conf);
	this._textbox.config(conf);
};

/**
 * <p>
 * 日期控件渲染函数
 * </p>
 * 
 * @function
 * @return {Dom} 渲染后的Dom节点
 */
zxt.ui.Datebox.prototype.render = function() {
	var dom = null;

	if (this._skeleton == null) {
		this._skeleton = $("<div class='zxt-skeleton' style='width:100%'>");
	}
	;

	if (this.mode() == "LABEL") {
		dom = $("<div class='zxt-Label'>");
		var label = this.getLabel();
		if (!zxt.util.isAvailable(label)) {
			label = "&nbsp;";
		}
		;
		dom.html(label);
	} else if (this.mode() == "MASK") {
		dom = $("<div class='zxt-Label'>");
		dom.html(this.$Format);
	} else {
		dom = this.renderSelf();
	}
	;

	if (dom != this._inner) {
		this._inner = dom;
		this._skeleton.empty();
		this._skeleton.append(dom);
	}
	;
	return this._skeleton.get(0);

};

/**
 * <p>
 * 日期控件渲染函数
 * </p>
 * 
 * @function
 * @return {Dom} 渲染后的Dom节点
 */
zxt.ui.Datebox.prototype.renderSelf = function() {
	var host = this;

	this._textbox.$Hide = this.$Hide;

	if (!this.image()) {
		var tdom = this._textbox.render();
		return tdom;
	}

	/*
	 * 日期控件中的输入框控件的失去焦点方法同时调用日期控件的失去焦点方法
	 */
	this._textbox.whenBlur = function() {
		host.whenBlur();
	};

	if (this._$holderPanelDom == null) {
		this._$holderPanel = new zxt.ui.TablePanel(1, 2);//初始化一行两列的容器
		this._$holderPanelDom = this._$holderPanel.render();
		$(this._$holderPanelDom).css("table-layout", "fixed");
		$(this._$holderPanel.getCell(0, 0)).width("100%");
		$(this._$holderPanel.getCell(0, 1)).width("16");

		this._jqImage = new zxt.ui.Icon();
		this._jqImage.image(ZxtCalendarImagePath + "/efcalendar_icon.gif ");
		this._jqImage.width("16px");
		this._jqImage.height("16px");
		this._jqImage.clickFunc(function() {
			host.onPopImageClick();//绑定日期控件图片按钮事件
		});

		this.addChild(this._jqImage);
		this._jqImageDom = this._jqImage.render();

		$(this._$holderPanel.getCell(0, 0)).append(this._textbox.render());
		$(this._$holderPanel.getCell(0, 1)).attr("width", "16px").append(
				this._jqImageDom);
	} else {
		this._textbox.render();
		this._jqImage.render();
	}
	;

	return this._$holderPanelDom;
};


/**
 * <p>
 * 日期控件值变化函数
 * </p>
 * 
 * @function
 * @param {zxt.ui.*} child 子控件对象
 * @param {string} old 控件原先的值
 * @param {string} now 控件现在的值
 * @return {boolean} valueChange事件是否继续交给父控件处理
 */
zxt.ui.Datebox.prototype._onChildValueChange = function(child, old, now) {
	var ret = this.onChildValueChange(child, old, now);
	if (ret == false)
		return;

	var parent = this.getParent();
	if (zxt.util.isValue(parent))
		return parent._onChildValueChange(this, old, now);
};

/**
 * <p>
 * 日期控件值变化函数
 * </p>
 * 
 * @function
 * @param {zxt.ui.*} child 子控件对象
 * @param {string} old 控件原先的值
 * @param {string} now 控件现在的值
 * @return {boolean} valueChange事件是否继续交给父控件处理
 */
zxt.ui.Datebox.prototype.onChildValueChange = function(child, old, now) {
	var ret = this.onValueChange(old, now);
	return ret;
};

/**
 * <p>
 * 返回控件的值 私有函数 请直接调用getValue
 * </p>
 * 
 * @function
 * @return {string} 返回控件的值
 */
zxt.ui.Datebox.prototype.getSelfValue = function() {
	return this._textbox.getValue();
};

/**
 * <p>
 * 设置控件的值
 * </p>
 * 
 * @function
 * @param {string} v 设置控件的值
 */
zxt.ui.Datebox.prototype.setValue = function(v) {
	var _instance = this;
	this.validate(_instance, v);
	this._textbox.setValue(v);
};

/**
 * <p>
 * 日期控件失去焦点函数
 * </p>
 * @function
 */
zxt.ui.Datebox.prototype.whenBlur = function() {
	var _instance = this;
	var t = this._textbox;
	if (!t._isTip) {
		var inputV = t._$input.val();
		t.val(inputV.trim());
	}
	;
	t._decorate(true, true);
	this.validate(_instance, t.getValue());
};

/**
 * <p>
 * 日期控件图片单击事件 调用日历控件弹出
 * </p>
 * @function
 */
zxt.ui.Datebox.prototype.onPopImageClick = function() {
	if ( this.mode() =="READONLY") {
		return;
	};
	zxt.ui.Calendar.show(this._jqImageDom, this._textbox, this.$Format, true);
};

/**
 * <p>
 * 日历控件按键监听函数
 * 绑定回车键为日历框弹出
 * </P>
 * @function
 */
zxt.ui.Datebox.prototype.onKeyDown = function(keyCode) {
	switch (keyCode) {
	case 13:
		this.onPopImageClick();
		break;
	}
};

/**
 * <p>
 * 日期值校验函数
 * </P>
 * @function
 * @param {string} value 被校验的值
 * @return {boolean} 是否校验通过
 */
zxt.ui.Datebox.prototype._validate = function(value) {
	var dateRegx = this.format();
	var yyyyRegx = "[0-9]{4}";
	var ccRegx = "[0-9]{2}";
	var yyRegx = "[0-9]{2}";
	var mmRegx = "(0[0-9]|[1][012])";
	var ddRegx = "([012][0-9]|3[01])";
	dateRegx = dateRegx.replace(/yyyy/, yyyyRegx);
	dateRegx = dateRegx.replace(/cc/, ccRegx);
	dateRegx = dateRegx.replace(/yy/, yyRegx);
	dateRegx = dateRegx.replace(/mm/, mmRegx);
	dateRegx = dateRegx.replace(/dd/, ddRegx);
	dateRegx = new RegExp(dateRegx);
	return dateRegx.test(value);
};

/**
 * <p>
 * 日期控件工厂类
 * </P>
 * @class
 */
zxt.ui.DateboxFactory = function() {
	zxt.ui.InteractorFactory.call(this);
};

zxt.ui.DateboxFactory.prototype = new zxt.clazz();
zxt.ui.DateboxFactory.prototype.inheritFrom(zxt.ui.InteractorFactory);

/**
 * <p>
 * 日期控件工厂类获得对象方法
 * </P>
 * @function
 * 返回日期控件对象
 */
zxt.ui.DateboxFactory.prototype.getInstance = function() {
	return new zxt.ui.Datebox();
};

/**
 * <p>
 * 根据传入的DOM元素, 解析传入的相关属性, 创建相应的区域 目前方法为空
 * </p>
 * @function
 * @static
 * @param {DOM} elem 传入的DOM元素
 */
zxt.ui.DateboxFactory.prototype.parse = function(elem) {
};


zxt.ui.TimeConfig = {
	clock : zxt.cfg.IMAGES_PATH + '/zxt_clock_clock.png',
	clockMask : zxt.cfg.IMAGES_PATH + '/zxt_clock_mask.png',
	hourHand : zxt.cfg.IMAGES_PATH + '/zxt_clock_hourhand.png',
	minHand : zxt.cfg.IMAGES_PATH + '/zxt_clock_minhand.png',
	secHand : zxt.cfg.IMAGES_PATH + '/zxt_clock_sechand.png'
};

/**
 * <p>
 * Clock 时钟控件
 * </p>
 * @class
 */
zxt.ui.Time = function(flag) {
	zxt.ui.Widget.call(this);
	this._bFlag = flag || 1;
	this._$jqDom = $("<div class='zxt-Widget'>");
};

zxt.defineClazz(zxt.ui.Time, zxt.ui.Widget);

/**
 * <p>
 * 返回控件类型
 * </p>
 * 
 * @function
 * @returns {string} "zxt.ui.Time"
 */
zxt.ui.Time.prototype.getType = function() {
	return "zxt.ui.Time";
};

/**
 * <p>
 * 渲染CLOCK的DOM节点
 * </p>
 * 
 * @function
 * @return {DOM} 渲染成的DOM节点
 */
zxt.ui.Time.prototype.renderSelf = function() {
	var host = this;
	if (this._bFlag == 1) {
		this._initializeE();
	} else if (this._bFlag == 3) {
		this._initializeP();
	}
	setInterval(function() {
		host.displayTime();
	}, 100);
	return this._$jqDom.get(0);
};

/**
 * <p>
 * 获取并展示时间
 * </p>
 * 
 * @function
 * @param {Date} t 需要展示的时间 不传的话采用当前时间
 */
zxt.ui.Time.prototype.displayTime = function(t) {
	var time = t || new Date();
	if (this._bFlag == 1) {
		this._timeE(time);
	}
	if (this._bFlag == 3) {
		this._timeP(time);
	}

};

/**
 * <p>
 * 初始化电子钟容器
 * </p>
 * @function
 */
zxt.ui.Time.prototype._initializeE = function() {
	this._tablePanel = new zxt.ui.TablePanel(1, 3);
	this._panelDom = this._tablePanel.render();
	this._$jqDom.empty().append(this._panelDom);
};

/**
 * <p>
 * 初始化电子钟钟面
 * </p>
 * @function
 */
zxt.ui.Time.prototype._initializeP = function() {
	this._cb = document.createElement("div");
	this._oNode = this._cb;
	this._$jqDom.empty().append(this._cb);

	this._clockbg = new Image();
	this._clockbg.src = zxt.ui.TimeConfig.clock;

	this._hourhand = new Image();
	this._hourhand.src = zxt.ui.TimeConfig.hourHand;

	this._minhand = new Image();
	this._minhand.src = zxt.ui.TimeConfig.minHand;

	this._sechand = new Image();
	this._sechand.src = zxt.ui.TimeConfig.secHand;

	this._clock_mask = new Image();
	this._clock_mask.src = zxt.ui.TimeConfig.clockMask;

	this._offsetWidth = -7;
	this._offsetHeight = -7;
	this._aMonths = [ "Jan", "Feb", "Mar", "Apr", "May", "June", "July",
			"August", "Sep", "Oct", "Nov", "Dec" ];
};

/**
 * <p>
 * 初始化电子钟时间
 * </p>
 * @function
 */
zxt.ui.Time.prototype._timeE = function(time) {
	var h = time.getHours()
	var m = time.getMinutes()
	var s = time.getSeconds()
	if (m < 10) {
		m = "0" + m
	}
	if (s < 10) {
		s = "0" + s
	}

	$(this._tablePanel.getCell(0, 0)).text(h + ":");
	$(this._tablePanel.getCell(0, 1)).text(m + ":");
	$(this._tablePanel.getCell(0, 2)).text(s);
};

/**
 * <p>
 * 第三种样式的时钟
 * <p>
 * @function
 */
zxt.ui.Time.prototype._PoorClock = function() {

	if (this._PoorClock.hasStyle != true) {
		var cbs = this._cb.style;
		cbs.background = "purple";
		cbs.color = "yellow";
		cbs.padding = "3px";
		cbs.border = "solid 1px yellow";
		cbs.fontSize = "12px";
		cbs.height = "auto";
		cbs.width = "auto";
		cbs.fontFamily = "Verdana";
		cbs.whiteSpace = "nowrap";
		cbs.fontWeight = "bold";

		if (document.all && document.uniqueID) {

			try {
				cbs.cursor = "hand";
				cbs.filter = "progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true')";
			} catch (e) {
			}
			;
		} else {
			cbs.cursor = "pointer";
		}
		;
		this._PoorClock.hasStyle = true;
	}
	;
};

/**
 * <p>
 * 第三种样式的时钟
 * <p>
 * @function
 * @param {Date} now 当前时间 
 */
zxt.ui.Time.prototype._timeP = function(now) {
	this._cb.innerHTML = '<canvas width=0 height=0></canvas>';
	var cbs = this._cb.style;
	cbs.cssText = "-moz-border-radius:6px;"
	cbs.width = this._clockbg.width + "px";
	cbs.height = this._clockbg.width + "px";
	cbs.position = "relative";
	var canvas = this._cb.getElementsByTagName("canvas")[0];

	if (!canvas || !canvas.getContext) {

		if (document.all && document.namespaces && document.uniqueID) {
			/* IE5.5+ Version */
			try {
				var cw = this._clockbg.width;
				var ch = this._clockbg.height;

				var s1 = 'position:absolute;top:0;overflow:xhidden;left:0;filter:progid:DXImageTransform.Microsoft.Matrix(sizingmethod=\'auto expand\');z-index:';
				var s2 = 'style="position:absolute;top:0;left:0;;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=';

				this._cb.innerHTML = [
						/* 1 */'<div style="' + s1 + '1;width:' + cw
								+ 'px;height:' + ch + 'px;"><div ' + s2
								+ this._clockbg.src + ');width:' + cw
								+ ';height:' + ch + 'px;"></div></div>',
						/* 1 */'<div style="' + s1 + '1;width:' + cw
								+ 'px;height:' + ch + 'px;"><div ' + s2
								+ this._hourhand.src + ');width:'
								+ this._hourhand.width + ';height:'
								+ this._hourhand.height + 'px;"></div></div>',
						/* 2 */'<div style="' + s1 + '1;width:' + cw
								+ 'px;height:' + ch + 'px;"><div ' + s2
								+ this._minhand.src + ');width:'
								+ this._minhand.width + ';height:'
								+ this._minhand.height + 'px;"></div></div>',
						/* 3 */'<div style="' + s1 + '1;width:' + cw
								+ 'px;height:' + ch + 'px;"><div ' + s2
								+ this._sechand.src + ');width:'
								+ this._sechand.width + ';height:'
								+ this._sechand.height + 'px;"></div></div>',
						/* 4 */'<div style="' + s1 + '1;width:' + cw
								+ 'px;height:' + ch
								+ 'px;cursor:hand;corsor:pointer;">1<div ' + s2
								+ this._clock_mask.src + ');width:'
								+ this._clock_mask.width + ';height:'
								+ this._clock_mask.height + 'px;"></div></div>', ]
						.join("");

				var divs = this._cb.childNodes;

				cw = cw + this._offsetWidth;
				ch = ch + this._offsetHeight;

				for ( var i = 1; i <= 3; i++) {
					var d = divs[i];
					var dd = d.getElementsByTagName("div")[0];

					d.staticLeft = (cw) / 2;
					d.staticTop = ch / 2;
					dd.style.left = (cw - dd.offsetWidth) / 2 + dd.offsetWidth
							/ 3 + "px";
					dd.style.top = ch / 2 + "px";
				}
				;

				var hoursAngle = (now.getHours() % 12) / 12 * 360 + 180;
				var minutesAngle = (now.getMinutes() / 60) * 360 + 180;
				var secondsAngle = (now.getSeconds() / 60) * 360 + 180;

				this._fnSetRotation(divs[1], hoursAngle, cw, ch);
				this._fnSetRotation(divs[2], minutesAngle, cw, ch);
				this._fnSetRotation(divs[3], secondsAngle, cw, ch);
			} catch (e) {
				this._PoorClock();
			}
			;

		} else {
			/* Other Brosers */
			this._PoorClock();
		}
		;
	} else {
		/* Canvas Version */
		try {

			var cw = this._clockbg.width;
			var ch = this._clockbg.height;

			canvas.width = cw;
			canvas.height = ch;

			canvas.style.background = "url(" + this._clockbg.src
					+ ") no-repeat";
			// canvas.style.position = "absolute";

			var offsetAngle = (180 / 360) * (Math.PI * 2);
			var minutesAngle = (now.getMinutes() / 60) * (Math.PI * 2)
					+ offsetAngle;
			var secondsAngle = (now.getSeconds() / 60) * (Math.PI * 2)
					+ offsetAngle;
			var hoursAngle = ((now.getHours() % 12) / 12) * (Math.PI * 2)
					+ offsetAngle;

			var context = canvas.getContext("2d");
			cw = cw + this._offsetWidth;
			ch = ch + this._offsetHeight;

			context.clearRect(0, 0, cw * 2, ch * 2);
			context.save();
			context.translate(cw / 2, ch / 2);

			context.save();
			context.rotate(minutesAngle);
			context.drawImage(this._minhand, -this._minhand.width / 2, 0,
					this._minhand.width, this._minhand.height);
			context.restore();

			context.save();
			context.rotate(hoursAngle);
			context.drawImage(this._hourhand, -this._hourhand.width / 2, 0,
					this._hourhand.width, this._hourhand.height);
			context.restore();

			context.save();
			context.rotate(secondsAngle);
			context.drawImage(this._sechand, -this._sechand.width / 2, 0,
					this._sechand.width, this._sechand.height);
			context.restore();

			context.translate(-cw / 2, -ch / 2);
			context.drawImage(this._clock_mask, 0, 0, this._clock_mask.width,
					this._clock_mask.height);
			context.restore();

		} catch (e) {
			this._PoorClock();
		}
		;

		canvas.style.cursor = "pointer";
	}
	;
};

/**
 * <p>
 * 指针旋转方法
 * <p>
 * @function
 * @param {Dom} oObj 指针的dom节点
 * @param {int} deg 旋转的角度
 * @param {int} cw 指针的宽度
 * @param {int} ch 指针的长度
 */
zxt.ui.Time.prototype._fnSetRotation = function(oObj, deg, cw, ch) {
	var deg2radians = Math.PI * 2 / 360;
	rad = deg * deg2radians;
	var costheta = Math.cos(rad);
	var sintheta = Math.sin(rad);

	try {
		oObj.filters.item(0).M11 = costheta;
		oObj.filters.item(0).M12 = -sintheta;
		oObj.filters.item(0).M21 = sintheta;
		oObj.filters.item(0).M22 = costheta;
	} catch (e) {

		this._PoorClock();
		return false;
	}
	;

	oObj.style.left = cw / 2 - oObj.offsetWidth / 2 + "px";
	oObj.style.top = ch / 2 - oObj.offsetHeight / 2 + "px";
};
